#include "hyperboloid.h"
#include "math.h"

//Constructeur par défaut
Hyperboloid::Hyperboloid()
{
    angle = 0.0f;
    nbPoints = 16;
    initialiser();
}

//Constructeur à 3 paramètres
Hyperboloid::Hyperboloid(float angle, int nbPoints)
    : angle(angle), nbPoints(nbPoints)
{
    initialiser();
}

//On initialise les différentes listes de notre hyperboloid
void Hyperboloid::initialiser()
{
    //On initialise les deux centres
    centreHaut = new Point(.0f, 1.0f, .0f);
    centreBas  = new Point(.0f, -1.0f, .0f);

    //On calcule les positions des sommets
    for(int i = 0; i < nbPoints; ++i)
    {
        float theta = 2.0 * PI / nbPoints * i;
        float x = sin(theta);
        float z = cos(theta);
        this->sommetsInferieurs.append(new Point(x, -1, z));
        this->sommetsSuperieurs.append(new Point());
    }

    //On associe les sommets aux faces
    for(int i = 0; i < nbPoints; ++i)
    {
        //On crée les faces des côtés
        QList<Point*> l;
        l.append(sommetsSuperieurs[i]);
        l.append(sommetsInferieurs[i]);
        l.append(sommetsInferieurs[(i+1)%nbPoints]);
        l.append(sommetsSuperieurs[(i+1)%nbPoints]);

        this->facesCotes.append(l);

        //On crée les faces du dessus
        QList<Point*> l2;
        l2.append(centreHaut);
        l2.append(sommetsSuperieurs[i]);
        l2.append(sommetsSuperieurs[(i+1)%nbPoints]);

        this->facesDessus.append(l2);

        //On crée les faces du dessous
        QList<Point*> l3;
        l3.append(centreBas);
        l3.append(sommetsInferieurs[(i+1)%nbPoints]);
        l3.append(sommetsInferieurs[i]);

        this->facesDessous.append(l3);
    }

    calculerPositionPointsSuperieurs();

}

//On calcule les positions des points supérieurs en fonction de l'angle
void Hyperboloid::calculerPositionPointsSuperieurs()
{
    for(int i = 0; i < nbPoints; ++i)
    {
        float theta = 2.0 * PI / nbPoints * i;
        this->sommetsSuperieurs[i]->setX(sin(theta + angle));
        this->sommetsSuperieurs[i]->setY(1.0f);
        this->sommetsSuperieurs[i]->setZ(cos(theta + angle));
    }
}

//On dessine notre hyperboloid
void Hyperboloid::dessiner()
{
    //On dessine les faces des côtés
    glBegin(GL_QUADS);
    for(int i = 0; i < facesCotes.count(); ++i)
    {
        for(int j = 0; j < facesCotes[i].count(); ++j)
        {
            glVertex3f(facesCotes[i][j]->getX(), facesCotes[i][j]->getY(), facesCotes[i][j]->getZ());
        }
    }
    glEnd();

    //On dessine les faces du dessus
    glBegin(GL_TRIANGLES);
    for(int i = 0; i < facesDessus.count(); ++i)
    {
        for(int j = 0; j < facesDessus[i].count(); ++j)
        {
            glVertex3f(facesDessus[i][j]->getX(), facesDessus[i][j]->getY(), facesDessus[i][j]->getZ());
        }

    }
    glEnd();

    //On dessine les faces du dessous
    glBegin(GL_TRIANGLES);
    for(int i = 0; i < facesDessous.count(); ++i)
    {
        for(int j = 0; j < facesDessous[i].count(); ++j)
        {
            glVertex3f(facesDessous[i][j]->getX(), facesDessous[i][j]->getY(), facesDessous[i][j]->getZ());
        }

    }
    glEnd();
}

//On change l'angle de notre hyperboloid
//On recalcule les positions des points supérieurs
void Hyperboloid::setAngle(float angle)
{
    if(this->angle != angle)
    {
        this->angle = angle;
        calculerPositionPointsSuperieurs();
    }
}

//Accesseur sur l'angle
float Hyperboloid::getAngle()
{
    return angle;
}
